package Brain;

/**
 *
 * @author jorgelainfiesta
 * @date Jul 14, 2012
 */
public class CalcuPostfix {
    private VectorPila<Double> operandos;
    private char[] operadores;
    
    /**
     * Constructor
     */
    public CalcuPostfix(){
        //Operadores permitidos
        this.operadores = new char[4];
        this.operadores[0] = '+';
        this.operadores[1] = '-';
        this.operadores[2] = '*';
        this.operadores[3] = '/';  
        this.operandos = new VectorPila();
    }
    
    /**
     * Determina si es un numero
     * @param numero
     * @return True si es numero 
     */
    public boolean esNumero(String numero){
        try{
            Double.parseDouble(numero);
            return true;
        }catch(NumberFormatException err){
            return false;
        }
    }
    
    /**
     * Determina si es un operador correcto
     * @param operador
     * @return True si es operador válido
     */
    public boolean esOperador(String operador){
        //Debe ser 1 solo caracter
        if(operador.length()>1)
            return false;
        boolean valido = false;
        //Revisa cada operador permitido para ver si es correcto
        for(char operador_v: operadores){
            if(operador.equals(operador_v+""))
                  valido = true;
        }
        return valido;
    }
    
    /**
     * Opera la operación en postfix que recibe
     * @param postfix
     * @return Resultado decimal
     * @throws Exception si hay errores en el postfix
     */
    public double operar(String postfix) throws Exception{
        postfix = postfix.trim(); //Limpiamos espacios del inicio y final
        operandos = new VectorPila(); //Mejor iniciamos con una nueva pila
        
        //Separamos el postfix por espacios
        String[] tokens = postfix.split(" ");
        double result = 0;
        //Tokens válidos, usado para reportar errores
        for(String token: tokens){
            int recognized = 0;
            //Revisamos si es número
            if(this.esNumero(token)){
                this.operandos.push(Double.parseDouble(token));
                recognized++;
            }
            //Revisamos si es operador válido
            if(this.esOperador(token)){
                //Deben haber al menos 2 operandos
                if(this.operandos.size()>=2){
                    //Iniciamos con primer elemento
                    result = this.operandos.pop();
                    //Operamos los operandos guardados segun el operador
                    while(!this.operandos.empty()){
                        switch(token.charAt(0)){
                            case '+':
                                result+=this.operandos.pop();
                            break;
                            case '-':
                                result-=this.operandos.pop();
                            break;
                            case '*':
                                result*=this.operandos.pop();
                            break;
                            case '/':
                                result/=this.operandos.pop();
                            break;
                        }
                    }
                    //Agregamos resultado a la pila como un operando nuevo
                    this.operandos.push(result);
                    recognized++;
                }else{
                    throw new Exception("Postfix inválido: deben haber al menos 2 operandos para operar");
                }
            }
            //Si no se ha identificado como número ni operador, lanzar error
            if(recognized==0)
                throw new Exception("Postfix inválido: operador inválido '"+token+"'");
            
        }
        result = operandos.pop();
        return result;
        //throw new Exception("Postfix inválido.");
    }
    
    
    

}
